df <- read.csv("https://raw.githubusercontent.com/gabrielvpina/dataScience/refs/heads/main/data/world-data-2023.csv")Relatório Formal com Tidyplots
Relatório formal de análise de dados feito utilizando a plataforma Quarto® com linguagem R. O relatório possui uma breve introdução dos dados juntamente com seu processamento e o delineamento de hipóteses. Testes estatísticos foram realizados para validar as hipóteses e o pacote Tidyplots foi utilizado para a construção de gráficos.
Data Science, Testes estatísticos, Tidyplots
Introdução
Esse relatório é complementar à Atividade Prática 06, realizada dia 28 de Outubro em sala de aula. O relatório possui o intuito de representar como um relatório de dados formal deve ser estruturado, juntamento com as operações de processamento de dados e códigos no R.
Resumo dos dados
Os dados utilizados aqui serão vindos da tabela world-data-2023.csv, que representa um compilado abrangente de indicadores globais por país, referente ao ano de 2023.
As principais categorias de dados incluem:
Demografia e Geografia: Informações sobre População, Densidade (P/Km2), Área Terrestre (Km2), População Urbana, Taxa de Natalidade, Taxa de Fertilidade e Expectativa de Vida.
Economia e Finanças: Dados vitais como Produto Interno Bruto (PIB), Índice de Preços ao Consumidor (IPC e sua variação), Código da Moeda, Salário Mínimo, Receita Tributária (%), Taxa de Imposto Total, e o Preço da Gasolina.
Saúde e Educação: Indicadores sociais cruciais, incluindo Mortalidade Infantil e Materna, proporção de Médicos por Mil, Despesas de Saúde do bolso próprio, e as taxas de matrícula bruta nos ensinos primário e superior.
Meio Ambiente e Recursos: Métricas ambientais como as Emissões de CO2 e a porcentagem de Terra Agrícola e Área Florestal.
Força de Trabalho e Segurança: Informações sobre a participação da Força de Trabalho, Taxa de Desemprego e o Tamanho das Forças Armadas.
Em resumo, é um dataset de múltiplas facetas destinado a fornecer um perfil detalhado e estatístico de cada país.
Importando os dados
Para importar esse dataset, utilizaremos a função read.csv() para importar um conjunto de dados diretamente da web. Atenção: Esse tipo de importação só é possível se os dados estiverem de forma integral no link.
Utilizando a função skim do pacote skimr nos dados:
# importar pacote
library(skimr)
# chamar função de resumo
skim(df)| Name | df |
| Number of rows | 195 |
| Number of columns | 35 |
| _______________________ | |
| Column type frequency: | |
| character | 26 |
| numeric | 9 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| Country | 0 | 1 | 4 | 32 | 0 | 195 | 0 |
| Density..P.Km2. | 0 | 1 | 1 | 6 | 0 | 137 | 0 |
| Abbreviation | 0 | 1 | 0 | 2 | 7 | 189 | 0 |
| Agricultural.Land…. | 0 | 1 | 0 | 6 | 7 | 169 | 0 |
| Land.Area.Km2. | 0 | 1 | 0 | 10 | 1 | 195 | 0 |
| Armed.Forces.size | 0 | 1 | 0 | 9 | 24 | 106 | 0 |
| Capital.Major.City | 0 | 1 | 0 | 22 | 3 | 193 | 0 |
| Co2.Emissions | 0 | 1 | 0 | 9 | 7 | 185 | 0 |
| CPI | 0 | 1 | 0 | 8 | 17 | 176 | 0 |
| CPI.Change…. | 0 | 1 | 0 | 7 | 16 | 87 | 0 |
| Currency.Code | 0 | 1 | 0 | 3 | 15 | 134 | 0 |
| Forested.Area…. | 0 | 1 | 0 | 6 | 7 | 162 | 0 |
| Gasoline.Price | 0 | 1 | 0 | 6 | 20 | 102 | 0 |
| GDP | 0 | 1 | 0 | 20 | 2 | 194 | 0 |
| Gross.primary.education.enrollment…. | 0 | 1 | 0 | 7 | 7 | 142 | 0 |
| Gross.tertiary.education.enrollment…. | 0 | 1 | 0 | 7 | 12 | 172 | 0 |
| Largest.city | 0 | 1 | 0 | 23 | 6 | 189 | 0 |
| Minimum.wage | 0 | 1 | 0 | 7 | 45 | 115 | 0 |
| Official.language | 0 | 1 | 0 | 22 | 1 | 78 | 0 |
| Out.of.pocket.health.expenditure | 0 | 1 | 0 | 6 | 7 | 161 | 0 |
| Population | 0 | 1 | 0 | 13 | 1 | 195 | 0 |
| Population..Labor.force.participation…. | 0 | 1 | 0 | 6 | 19 | 146 | 0 |
| Tax.revenue…. | 0 | 1 | 0 | 6 | 26 | 120 | 0 |
| Total.tax.rate | 0 | 1 | 0 | 7 | 12 | 157 | 0 |
| Unemployment.rate | 0 | 1 | 0 | 6 | 19 | 165 | 0 |
| Urban_population | 0 | 1 | 0 | 11 | 5 | 191 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| Birth.Rate | 6 | 0.97 | 20.21 | 9.95 | 5.90 | 11.30 | 17.95 | 28.75 | 46.08 | ▇▆▃▃▁ |
| Calling.Code | 1 | 0.99 | 360.55 | 323.24 | 1.00 | 82.50 | 255.50 | 506.75 | 1876.00 | ▇▂▂▁▁ |
| Fertility.Rate | 7 | 0.96 | 2.70 | 1.28 | 0.98 | 1.71 | 2.24 | 3.60 | 6.91 | ▇▅▃▂▁ |
| Infant.mortality | 6 | 0.97 | 21.33 | 19.55 | 1.40 | 6.00 | 14.00 | 32.70 | 84.50 | ▇▂▂▁▁ |
| Life.expectancy | 8 | 0.96 | 72.28 | 7.48 | 52.80 | 67.00 | 73.20 | 77.50 | 85.40 | ▂▃▅▇▅ |
| Maternal.mortality.ratio | 14 | 0.93 | 160.39 | 233.50 | 2.00 | 13.00 | 53.00 | 186.00 | 1150.00 | ▇▁▁▁▁ |
| Physicians.per.thousand | 7 | 0.96 | 1.84 | 1.68 | 0.01 | 0.33 | 1.46 | 2.94 | 8.42 | ▇▅▂▁▁ |
| Latitude | 1 | 0.99 | 19.09 | 23.96 | -40.90 | 4.54 | 17.27 | 40.12 | 64.96 | ▂▃▇▆▅ |
| Longitude | 1 | 0.99 | 20.23 | 66.72 | -175.20 | -7.94 | 20.97 | 48.28 | 178.07 | ▁▃▇▃▂ |
Primeiras impressões
Com o resumo dos dados em mãos, pode-se observar que diversas colunas que deveriam ser numéricas estão sendo lidas como strings. As principais causas são:
- Uso de vírgula para representar decimais, enquanto o R utiliza pontos
- Caracteres associados à porcentagens (ex: 23.12%)
- Caracteres associados à valores monetários (“$”)
Outra coisa para se atentar são os nomes das colunas, que antes continham espaços e símbolos na tabela original e agora tiveram modificações automáticas devido à função de importação do R.
# nomes vindos da importação
colnames(df) [1] "Country"
[2] "Density..P.Km2."
[3] "Abbreviation"
[4] "Agricultural.Land...."
[5] "Land.Area.Km2."
[6] "Armed.Forces.size"
[7] "Birth.Rate"
[8] "Calling.Code"
[9] "Capital.Major.City"
[10] "Co2.Emissions"
[11] "CPI"
[12] "CPI.Change...."
[13] "Currency.Code"
[14] "Fertility.Rate"
[15] "Forested.Area...."
[16] "Gasoline.Price"
[17] "GDP"
[18] "Gross.primary.education.enrollment...."
[19] "Gross.tertiary.education.enrollment...."
[20] "Infant.mortality"
[21] "Largest.city"
[22] "Life.expectancy"
[23] "Maternal.mortality.ratio"
[24] "Minimum.wage"
[25] "Official.language"
[26] "Out.of.pocket.health.expenditure"
[27] "Physicians.per.thousand"
[28] "Population"
[29] "Population..Labor.force.participation...."
[30] "Tax.revenue...."
[31] "Total.tax.rate"
[32] "Unemployment.rate"
[33] "Urban_population"
[34] "Latitude"
[35] "Longitude"
Vamos checar agora o total de valores vazios NAs no dataset:
# a função table() conta categorias do vetor gerado pela função is.na()
table(is.na(df))
FALSE TRUE
6774 51
São 51 itens vazios em um total de 6774 itens totais da tabela, isso representa aproximadamente 0.75% dos valores totais no nosso dataset.
Processamento dos dados
Inicialmente vamos corrigir os nomes das colunas e as colunas com porcentagens que estão sendo lidas como string devido ao caractere “%”.
Nomes das Colunas
A função colnames() retorna o nome das colunas de um dataset, ela também pode ser utilizada para enviar um novo conjunto de nomes para as colunas de um dataset.
# vamos usar a função colnames(df) para ver as colunas originais e ir inserindo os novos nomes no vertor "novos_nomes"
novos_nomes <- c(
"Pais",
"Densidade", # 'Density (P/Km2)'
"Abreviacao",
"TerraAgriculturaPercentual", # 'Agricultural Land( %)'
"AreaTerrestreKm2", # 'Land Area(Km2)'
"TamanhoForcasArmadas", # 'Armed Forces size'
"TaxaNatalidade", # 'Birth Rate'
"CodigoDiscagem", # 'Calling Code'
"CapitalCidadePrincipal", # 'Capital/Major City'
"EmissoesCO2", # 'Co2-Emissions'
"IPC", # 'CPI'
"MudancaIPCPercentual", # 'CPI Change (%)'
"CodigoMoeda", # 'Currency-Code'
"TaxaFertilidade", # 'Fertility Rate'
"AreaFlorestadaPercentual", # 'Forested Area (%)'
"PrecoGasolina", # 'Gasoline Price'
"PIB", # 'GDP'
"MatriculaPrimariaBrutaPercentual", # 'Gross primary education enrollment (%)'
"MatriculaSuperiorBrutaPercentual", # 'Gross tertiary education enrollment (%)'
"MortalidadeInfantil", # 'Infant mortality'
"MaiorCidade", # 'Largest city'
"ExpectativaVida", # 'Life expectancy'
"TaxaMortalidadeMaterna", # 'Maternal mortality ratio'
"SalarioMinimo", # 'Minimum wage'
"LinguaOficial", # 'Official language'
"GastoSaudeProprioBolso", # 'Out of pocket health expenditure'
"MedicosPorMil", # 'Physicians per thousand'
"Populacao",
"PopulacaoForcaTrabalhoPercentual", # 'Population: Labor force participation (%)'
"ReceitaFiscalPercentual", # 'Tax revenue (%)'
"TaxaImpostoTotal", # 'Total tax rate'
"TaxaDesemprego", # 'Unemployment rate'
"PopulacaoUrbana", # 'Urban_population'
"Latitude",
"Longitude"
)
# Usando a função colnames() para inserir os novos nomes de coluna
colnames(df) <- novos_nomes
# Mostrar novos nomes
colnames(df) [1] "Pais" "Densidade"
[3] "Abreviacao" "TerraAgriculturaPercentual"
[5] "AreaTerrestreKm2" "TamanhoForcasArmadas"
[7] "TaxaNatalidade" "CodigoDiscagem"
[9] "CapitalCidadePrincipal" "EmissoesCO2"
[11] "IPC" "MudancaIPCPercentual"
[13] "CodigoMoeda" "TaxaFertilidade"
[15] "AreaFlorestadaPercentual" "PrecoGasolina"
[17] "PIB" "MatriculaPrimariaBrutaPercentual"
[19] "MatriculaSuperiorBrutaPercentual" "MortalidadeInfantil"
[21] "MaiorCidade" "ExpectativaVida"
[23] "TaxaMortalidadeMaterna" "SalarioMinimo"
[25] "LinguaOficial" "GastoSaudeProprioBolso"
[27] "MedicosPorMil" "Populacao"
[29] "PopulacaoForcaTrabalhoPercentual" "ReceitaFiscalPercentual"
[31] "TaxaImpostoTotal" "TaxaDesemprego"
[33] "PopulacaoUrbana" "Latitude"
[35] "Longitude"
Corrigir colunas lidas como string
Colunas com porcentagem (%)
Para corrigir as colunas que possuem um caractere % em seus itens, utiliza-se uma substituição por um item vazio (““). Para isso emprega-se a função gsub() para substituir "%" -> "". Normalmente a função gsub() funciona individualmente para cada coluna, por isso deve-se utilizar a função lapply() associada a ela, de forma que gsub() funcione em um loop para as colunas selecionadas.
# colunas com caractere de porcentagem (%)
colunas_erradas <- c("TaxaDesemprego", "TaxaImpostoTotal", "ReceitaFiscalPercentual", "PopulacaoForcaTrabalhoPercentual", "GastoSaudeProprioBolso", "MatriculaSuperiorBrutaPercentual", "MatriculaPrimariaBrutaPercentual", "AreaFlorestadaPercentual", "MudancaIPCPercentual", "TerraAgriculturaPercentual")
# aplicando gsub nas colunas escolhidas
df[colunas_erradas] <- lapply(df[colunas_erradas], gsub, pattern = "%", replacement = "") # trocar porcentagem por vazio
# transformando as colunas em numericas
df[colunas_erradas] <- lapply(df[colunas_erradas], as.numeric)Colunas com cifrão ($)
Com isso resolvemos as colunas com %, agora vamos aplicar a mesma lógica para colunas com cifrão $. Entretanto 0 cifrão é um metacaractere em expressões regulares que geralmente indica o fim da string. Para tratar o $ como um caractere literal que você deseja remover, ele precisa ser “escapado” com barras invertidas duplas \\$.
colunas_cifrao <- c("SalarioMinimo", "PrecoGasolina")
df[colunas_cifrao] <- lapply(df[colunas_cifrao], gsub, pattern = "\\$", replacement = "")
df[colunas_cifrao] <- lapply(df[colunas_cifrao], as.numeric)Colunas com vírgula
A partir da substituição do cifrão nas colunas, é possível realizar a substituição das vírgulas nas colunas e convertê-las para colunas numéricas. Podemos checar com head(df) os nossos dados e selecionar as colunas erradas.
É necessário fazer uma diferença, pois em colunas como PopulacaoUrbana, Populacao, PIB e EmissoesCO2 existe um padrão diferente de notação, onde as vírgulas estão somente para diferenciar visualmente os milhates das centenas e das dezenas, e não uma representação decimal.
colunas_cifrao <- c("PIB")
df[colunas_cifrao] <- lapply(df[colunas_cifrao], gsub, pattern = "\\$", replacement = "")
colunas_virg <- c("PopulacaoUrbana", "Populacao", "PIB", "EmissoesCO2", "AreaTerrestreKm2", "Densidade", "TamanhoForcasArmadas")
df[colunas_virg] <- lapply(df[colunas_virg], gsub, pattern = ",", replacement = "")
df[colunas_virg] <- lapply(df[colunas_virg], as.numeric)Agora todas as colunas estão formatadas para as análises estatísticas e gráficos.
Análises Univariadas
A partir dos dados já convertidos podemos realizar análises de distribuição dos dados.
Densidade dos dados
# importar pacotes
library(tidyverse)
library(ggplot2)
library(tidyr)
library(dplyr)
colunas_para_plotar <- c(
"TaxaNatalidade",
"TaxaFertilidade",
"ExpectativaVida",
"TaxaDesemprego",
"TerraAgriculturaPercentual",
"AreaTerrestreKm2",
"EmissoesCO2",
"AreaFlorestadaPercentual",
"MortalidadeInfantil",
"TaxaImpostoTotal",
"PrecoGasolina",
"PopulacaoUrbana",
"SalarioMinimo",
"MedicosPorMil",
"Populacao",
"PopulacaoForcaTrabalhoPercentual",
"Densidade",
"TamanhoForcasArmadas"
)
df_longo <- df %>%
select(all_of(colunas_para_plotar)) %>%
pivot_longer(
cols = all_of(colunas_para_plotar),
names_to = "Variavel",
values_to = "Valor"
)
grafico_densidade <- ggplot(df_longo, aes(x = Valor)) +
geom_density(fill = "#2a78b5", alpha = 0.7, color = "white") +
# geom_histogram(bins = 30, fill = "#2a78b5", alpha = 0.7, color = "white") +
facet_wrap(~ Variavel, scales = "free", ncol = 3) +
labs(
title = "Distribuição de Indicadores Globais por País (2023)",
x = "Valor",
y = "Densidade"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
strip.text = element_text(face = "bold")
)
print(grafico_densidade)Teste de Normalidade
O teste de normalidade é crucial para verificar se os dados numéricos seguem uma distribuição normal, o que é um pré-requisito para muitos testes estatísticos paramétricos (como o Teste t de Student ou ANOVA).
Teste de Shapiro-Wilk
O teste de Shapiro-Wilk fornece as seguintes informações sobre um conjunto de dados:
- Os dados seguem uma distribuição normal.
- Os dados não seguem uma distribuição normal.
Entende-se conjunto de dados (no caso analisado), cada coluna com um índice sobre os dados de cada país.
Distribuição normal: É a mais importante distribuição de probabilidade, sendo aplicada em inúmeros fenômenos e utilizada para o desenvolvimento teórico de estatística. É também conhecida como distribuição de Gauss, Laplace ou Laplace-Gauss.
Teste Básico de Shapiro-Wilk no R
Para uma análise básica do teste de normalidade, deve-se inserir o vetor de interesse (uma coluna numérica) com os dados a serem analisados, usa-se a função shapiro.test():
test1 <- shapiro.test(df$MortalidadeInfantil)
test1
Shapiro-Wilk normality test
data: df$MortalidadeInfantil
W = 0.86165, p-value = 4.174e-12
A interpretação do p-valor:
- p > 0.05: Os dados podem ser considerados normais. Você pode prosseguir com testes paramétricos (como ANOVA).
- P < 0.05: Os dados não seguem uma distribuição normal. Você deve considerar transformações ou usar testes não-paramétricos (como Kruskal-Wallis).
Teste de Shapiro-Wilk para o conjunto de dados
# selecionando o mesmo conjunto de dados dos meus plots
colunas_para_testar <- c(
"TaxaNatalidade",
"TaxaFertilidade",
"ExpectativaVida",
"TaxaDesemprego",
"TerraAgriculturaPercentual",
"AreaTerrestreKm2",
"EmissoesCO2",
"AreaFlorestadaPercentual",
"MortalidadeInfantil",
"TaxaImpostoTotal",
"PrecoGasolina",
"PopulacaoUrbana",
"SalarioMinimo",
"MedicosPorMil",
"Populacao",
"PopulacaoForcaTrabalhoPercentual",
"Densidade",
"TamanhoForcasArmadas"
)
# criar dataframe para armazenar os resultados
resultados_normalidade <- data.frame(
Variavel = character(),
ShapiroWilk_p_value = numeric(),
Interpretacao = character(),
stringsAsFactors = FALSE
)
# realizar o teste de normalidade para todas as colunas selecionadas
for (col in colunas_para_testar) {
# filtra valores não-ausentes (NA) para o teste
dados_filtrados <- na.omit(df[[col]])
if (length(dados_filtrados) < 3) {
p_value <- NA
interpretacao <- "Amostra muito pequena (N < 3)"
} else {
teste <- shapiro.test(dados_filtrados)
p_value <- teste$p.value
if (p_value < 0.05) {
interpretacao <- "Rejeita H0: Não Normal"
} else {
interpretacao <- "Não Rejeita H0: Distribuição Normal"
}
}
# adicionar o resultado ao dataframe
resultados_normalidade[nrow(resultados_normalidade) + 1, ] <- c(col, p_value, interpretacao)
}
# plotar via pacote gt
library(gt)
gt(resultados_normalidade)| Variavel | ShapiroWilk_p_value | Interpretacao |
|---|---|---|
| TaxaNatalidade | 2.69875917384226e-08 | Rejeita H0: Não Normal |
| TaxaFertilidade | 1.12087320173536e-10 | Rejeita H0: Não Normal |
| ExpectativaVida | 8.02908862338933e-05 | Rejeita H0: Não Normal |
| TaxaDesemprego | 1.57916563935281e-10 | Rejeita H0: Não Normal |
| TerraAgriculturaPercentual | 0.000598713593217884 | Rejeita H0: Não Normal |
| AreaTerrestreKm2 | 9.54101633213065e-26 | Rejeita H0: Não Normal |
| EmissoesCO2 | 7.39820077387315e-28 | Rejeita H0: Não Normal |
| AreaFlorestadaPercentual | 3.42786649089169e-06 | Rejeita H0: Não Normal |
| MortalidadeInfantil | 4.17419654709054e-12 | Rejeita H0: Não Normal |
| TaxaImpostoTotal | 2.42986434096834e-16 | Rejeita H0: Não Normal |
| PrecoGasolina | 0.965803570725806 | Não Rejeita H0: Distribuição Normal |
| PopulacaoUrbana | 7.16551678317921e-27 | Rejeita H0: Não Normal |
| SalarioMinimo | 9.15869372810545e-17 | Rejeita H0: Não Normal |
| MedicosPorMil | 3.42455848258256e-10 | Rejeita H0: Não Normal |
| Populacao | 1.18691069208869e-27 | Rejeita H0: Não Normal |
| PopulacaoForcaTrabalhoPercentual | 0.300194782119932 | Não Rejeita H0: Distribuição Normal |
| Densidade | 3.81361558772807e-29 | Rejeita H0: Não Normal |
| TamanhoForcasArmadas | 3.04552884606606e-23 | Rejeita H0: Não Normal |
A maioria das nossas variáveis não segue a distribuição normal. Isso condiz com a natureza dos nossos dados, pois não se trata de dados gerados ao acaso, mas sim dados do mundo real influenciados por políticas internacionais e normas públicas, que podem adicionar todo tipo de viés aos dados absolutos.
Exemplo de distribuição que não segue a normalidade:
ggplot(df, aes(x = MortalidadeInfantil))+
geom_density(fill = "#b5692a", alpha = 0.7, color = "white") +
theme_minimal()As variáveis PrecoGasolina e PopulacaoForcaTrabalhoPercentual são as únicas que apresentaram uma distribuição normal no nosso dataset.
Exemplo de distribuição normal:
ggplot(df, aes(x = PrecoGasolina))+
geom_density(fill = "#2fca49", alpha = 0.7, color = "white") +
theme_minimal()Correlação das Variáveis
Observa-se que algumas variáveis pertencem à mesma categoria de medida. Pode-se selecionar variáveis com medidas sócio-econômicas e observar se há correlação entre elas no nosso dataset.
Variáveis Sócio-Econômicas
Colunas que envolvem as informações sobre saúde pública, economia e geografia da populção.
colunas_para_correlacionar <- c(
"TaxaNatalidade",
"TaxaFertilidade",
"ExpectativaVida",
"TaxaDesemprego",
"MortalidadeInfantil",
"TaxaImpostoTotal",
"SalarioMinimo",
"Densidade"
)
# importar pacote
library(GGally)
# correlatograma
ggpairs(df, columns = colunas_para_correlacionar, ggplot2::aes(fill="#3d85bc", alpha=0.6)) Variáveis Ambientais
Parâmetros relacionados com as atividades agrícolas e florestais do ambiente.
colunas_para_correlacionar_amb <- c(
"TerraAgriculturaPercentual",
"AreaTerrestreKm2",
"EmissoesCO2",
"AreaFlorestadaPercentual",
"PopulacaoUrbana"
)
# importar pacote
library(GGally)
# correlatograma
ggpairs(df, columns = colunas_para_correlacionar_amb, ggplot2::aes(fill="#3d85bc", alpha=0.6)) Testes Estatísticos
Testes estatísticos funcionam baseados na observação de várias amostras pertencentes à um grupo maior. As diferenças nas médias nos diferentes grupos que mostram a significância estatística de um teste. No caso do dataset utilizado, somente temos as amostras, sem nenhum grupo maior para fazer um teste.
A fim de contornar esse problema, é necessário formar grupos com as amostras. Para isso é necessário importar os dados de países e continentes - a comparação de grandes grupos (continentes) vai permitir a aplicabilidade dos testes.
# importar dataset
continents <- read.csv("https://gist.githubusercontent.com/stevewithington/20a69c0b6d2ff846ea5d35e5fc47f26c/raw/13716ceb2f22b5643ce5e7039643c86a0e0c6da6/country-and-continent-codes-list-csv.csv")
colnames(continents)[1] "Continent_Name" "Continent_Code"
[3] "Country_Name" "Two_Letter_Country_Code"
[5] "Three_Letter_Country_Code" "Country_Number"
Vamos usar a variável Two_Letter_Country_Code para realizar um JOIN entre as duas tabelas.
# importar pacote
library(dplyr)
# vamos unir os itens do continents (direita) para os itens do df (esquerda) - por isso um LEFT JOIN
df2 <- left_join(df,continents, by=c("Abreviacao"="Two_Letter_Country_Code"))
colnames(df2) [1] "Pais" "Densidade"
[3] "Abreviacao" "TerraAgriculturaPercentual"
[5] "AreaTerrestreKm2" "TamanhoForcasArmadas"
[7] "TaxaNatalidade" "CodigoDiscagem"
[9] "CapitalCidadePrincipal" "EmissoesCO2"
[11] "IPC" "MudancaIPCPercentual"
[13] "CodigoMoeda" "TaxaFertilidade"
[15] "AreaFlorestadaPercentual" "PrecoGasolina"
[17] "PIB" "MatriculaPrimariaBrutaPercentual"
[19] "MatriculaSuperiorBrutaPercentual" "MortalidadeInfantil"
[21] "MaiorCidade" "ExpectativaVida"
[23] "TaxaMortalidadeMaterna" "SalarioMinimo"
[25] "LinguaOficial" "GastoSaudeProprioBolso"
[27] "MedicosPorMil" "Populacao"
[29] "PopulacaoForcaTrabalhoPercentual" "ReceitaFiscalPercentual"
[31] "TaxaImpostoTotal" "TaxaDesemprego"
[33] "PopulacaoUrbana" "Latitude"
[35] "Longitude" "Continent_Name"
[37] "Continent_Code" "Country_Name"
[39] "Three_Letter_Country_Code" "Country_Number"
Agora temos ambos os conjuntos no mesmo dataset df2.
Plot com ggplot
A partir desses dados vamos fazer uma análise comparativa entre os continentes.
Transposição do Dataset
library(dplyr)
library(ggplot2)
library(tidyr)
# Usando o pacote "dplyr" para filtrar os NAs da coluna Continent_Name
df_limpo <- df2 %>%
filter(!is.na(Continent_Name)) %>% # o "!" significa uma negativa
filter(Densidade <= 5000) # Para remover micro estados com pop. grandes
#===============================================================================
# Extender o dataset para que todas as variáveis possam ser acessadas
# Colunas não numéricas
colunas_id <- c(
"Pais",
"Abreviacao",
"CodigoDiscagem",
"CapitalCidadePrincipal",
"MaiorCidade",
"LinguaOficial",
"CodigoMoeda",
"Continent_Name",
"Continent_Code",
"Country_Name",
"Three_Letter_Country_Code",
"Country_Number",
"Latitude",
"Longitude"
)
colunas_indicadores_numericos <- df_limpo %>%
# Seleciona todas as colunas que NÃO estão na lista de IDs
select(-all_of(colunas_id)) %>%
# E então seleciona daquelas, apenas as que são NUMÉRICAS (double/integer)
select(where(is.numeric)) %>%
colnames()
df_limpo$IPC <- as.numeric(df_limpo$IPC)
# função pivot_longer() -> extender o dataset na vertical
df_longo_indicadores <- df_limpo %>%
pivot_longer(
cols = all_of(colunas_indicadores_numericos),
names_to = "Indicador",
values_to = "Valor",
values_drop_na = FALSE
)Agora tempos o dataframe df_longo_indicadores, que é uma transposição do dataset orignial (manteve algumas colunas, mas outras foram transpostas em linhas). Segue a nova estrutura dele:
gt(head(df_longo_indicadores))| Pais | Abreviacao | CodigoDiscagem | CapitalCidadePrincipal | IPC | CodigoMoeda | MaiorCidade | LinguaOficial | Latitude | Longitude | Continent_Name | Continent_Code | Country_Name | Three_Letter_Country_Code | Country_Number | Indicador | Valor |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | Densidade | 60.00 |
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | TerraAgriculturaPercentual | 58.10 |
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | AreaTerrestreKm2 | 652230.00 |
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | TamanhoForcasArmadas | 323000.00 |
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | TaxaNatalidade | 32.49 |
| Afghanistan | AF | 93 | Kabul | 149.9 | AFN | Kabul | Pashto | 33.93911 | 67.70995 | Asia | AS | Afghanistan, Islamic Republic of | AFG | 4 | EmissoesCO2 | 8672.00 |
Agora é possível selecionar um subset de características e analisar de forma junta em múltiplos boxplots, que vão apresentar as tendências dos continentes.
Criação dos Plots
Variáveis Sócio-Econômicas
Colunas que envolvem as informações sobre saúde pública, economia e geografia da populção.
soc_eco <- c(
"TaxaNatalidade",
"TaxaFertilidade",
"ExpectativaVida",
"TaxaDesemprego",
"MortalidadeInfantil",
"TaxaImpostoTotal",
"SalarioMinimo",
"Densidade"
)
df_longo_indicadores %>%
filter(Indicador %in% soc_eco) %>%
ggplot(aes(x = Continent_Name, y = Valor, color = Indicador, fill=Indicador)) +
geom_boxplot(alpha=0.6) +
geom_jitter( alpha=0.6) +
facet_wrap(~ Indicador, scales = "free", ncol = 2) +
theme_minimal() +
theme(
axis.text.x = element_text(angle=45,hjust=1,vjust=1),
legend.position = "top"
)Variáveis Ambientais
Parâmetros relacionados com as atividades agrícolas e florestais do ambiente.
amb <- c(
"TerraAgriculturaPercentual",
"AreaTerrestreKm2",
"EmissoesCO2",
"AreaFlorestadaPercentual",
"PopulacaoUrbana"
)
df_longo_indicadores %>%
filter(Indicador %in% amb) %>%
ggplot(aes(x = Continent_Name, y = Valor, color = Indicador, fill=Indicador)) +
geom_boxplot(alpha=0.6) +
geom_jitter( alpha=0.6) +
facet_wrap(~ Indicador, scales = "free", ncol = 2) +
theme_minimal() +
theme(
axis.text.x = element_text(angle=45,hjust=1,vjust=1),
legend.position = "top"
)Testes estatísticos - Parte II
Anteriormente foi realizado o teste de Shapiro-Wilk, que informa se a distribuição de uma variável (ou dos resíduos de um modelo) desvia significativamente da distribuição normal. Ou seja, se na distribuição de um dos índices por país (População urbana, por exemplo) está seguindo uma distribuição normal em todos os países listados.
O teste de Shapiro-Wilk é também classificado como um teste de suposição (pré-teste/diagnóstico). Ele vai indicar a normalidade dos dados para realização de um teste primário (teste de hipótese), como uma Análise de Variâncias (ANOVA).
Como visto anteriormente, a princípio a ANOVA só pode ser realizada com dados paramétricos (dados com distribuição normal).
Análise de Variância (ANOVA)
A partir dos resultados, seleciona-se as características que possuem uma distribuição seguindo a curva normal (PrecoGasolina e PopulacaoForcaTrabalhoPercentual).
Preço da Gasolina
Modelo básico de ANOVA
A função aov() do pacote básico do R é a responsável por fazer a análise de variância dos dados. Um modelo de ANOVA deve ser feito entre uma variável categórica, como Continent_Name (representando um grupo maior dos dados individuais) e uma variável numérica - nesse caso o preço da gasoline (PrecoGasolina).
Criar subset somente com a coluna PrecoGasolina
gas <- df_longo_indicadores[df_longo_indicadores$Indicador == "PrecoGasolina", ]Modelo ANOVA
# Criar variável modelo para armazenar os dados da função aov()
modelo <- aov(Valor ~ Continent_Name, data = gas)
# Mostrar informações do modelo
summary(modelo) Df Sum Sq Mean Sq F value Pr(>F)
Continent_Name 5 5.034 1.0069 9.361 6.7e-08 ***
Residuals 171 18.394 0.1076
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
16 observations deleted due to missingness
A linha aov(Valor ~ Continent_Name, data = gas) pode ser traduzida como: Realizar uma análise de variância com os valores numéricos da coluna Valor em fator das categorias presentes em Continent_Name, sendo todas essas colunas pertencentes ao dataset gas.
O resultado da coluna Pr(>F) representa o P-Valor da ANOVA, onde sua interpretação é que:
- Quando
Pr(>F)> 0.05: Não há diferença entre as médias das categorias no valor escolhido - Quando
Pr(>F)< 0.05: Há diferença significativa entre as médias dos grupos analisados
No caso o P-Valor da variável modelo é de 6.7e-08, que representa um valor muito abaixo que 0.05, o que pode evidenciar uma diferença clara nas médias entre os grupos.
Uma das desvantagens da ANOVA é a falta de especificidade na análise, não evidenciando quais grupos diferem e qual o grau de diferença.
Plot de ANOVA com ggstatsplot
# ANOVA com pacote ggstatsplot()
# install.packages("ggstatsplot")
library(ggstatsplot)
ggstatsplot::ggbetweenstats(gas, Continent_Name, Valor, title = "Distribuição do Preço da Gasolina por Continente")